<template>
    <div class="room_com" ref="comRef">

        <div ref="containerRef" class="container_box"></div>
        
        <div class="left_box" name="leftBox" v-if="leftShow === 'leftBox'">
            <div class="left_cell" @click="alarmFn" :class="{'selct_left_cell': leftBtnStatus.alarm}">
                <img src="@/assets/images/3D/btns/ycsb.png" alt="">
                <span>告警监控</span>
            </div>
            <!-- <div class="left_cell" @click="spaceFn"  :class="{'selct_left_cell': leftBtnStatus.space}">
                <img src="@/assets/images/3D/btns/kjlyl.png" alt="">
                <span>空间</span>
            </div> -->
            <div class="left_cell" @click="bitFn"  :class="{'selct_left_cell': leftBtnStatus.bit}">
                <img src="@/assets/images/3D/btns/up.png" alt="">
                <span>U位</span>
            </div>
            <!-- <div class="left_cell" @click="humidityFn"  :class="{'selct_left_cell': leftBtnStatus.humidity}">
                <img src="@/assets/images/3D/btns/wdj.png" alt="">
                <span>温度</span>
            </div>
            <div class="left_cell" @click="bearingFn"  :class="{'selct_left_cell': leftBtnStatus.bearing}">
                <img src="@/assets/images/3D/btns/zl.png" alt="">
                <span>承重</span>
            </div>
            <div class="left_cell" @click="powerwasteFn"  :class="{'selct_left_cell': leftBtnStatus.powerwaste}">
                <img src="@/assets/images/3D/btns/gh2.png" alt="">
                <span>功耗</span>
            </div> -->
        </div>

        <!-- 单机机柜的机柜详情展示页 -->
        <div class="rittal_box" ref="rittalRef">
            <div class="rittal_box_top">
                <span>机柜详细信息</span>
                <div class="close_icon" @click="closeRittalDialog">
                    <el-icon><Close /></el-icon>
                </div>
            </div>
            <div class="rittal_box_content">
                <div class="rittal_box_line">
                    <div class="rittal_box_label">
                        <span>名称：</span>
                    </div>
                    <div class="rittal_box_value">
                        <span>{{ clickForm.cabinetname  }}</span>
                    </div>
                </div>
                <div class="rittal_box_line">
                    <div class="rittal_box_label">
                        <span>告警：</span>
                    </div>
                    <div class="rittal_box_value">
                        <span>{{ clickForm.cabinetAlarmCount||0  }}</span>
                    </div>
                </div>
                <div class="rittal_box_line">
                    <div class="rittal_box_label">
                        <span>U位使用率：</span>
                    </div>
                    <div class="rittal_box_value">
                        <span>{{ clickForm.cabinetuUsage }}%</span>
                    </div>
                </div>
                <div class="rittal_box_use">
                    <div class="rittal_width" :style="`--width-num: ${Number(clickForm.cabinetuUsage)}%`"></div>
                </div>
            </div>
        </div>

        <!-- 双击机柜展示机柜信息 -->
         <div class="rittal_info" name="rittalInfo" v-if="leftShow === 'rittalInfo'">
            <div class="rittal_info_title">
                <div class="back_icon" @click="backToUp">
                    <el-icon><ArrowLeftBold /></el-icon>
                </div>
                <span>详细信息</span>
            </div>
            <div class="rittal_info_contetn">
                <div class="rittal_box_line">
                    <div class="rittal_box_label">
                        <span>名称：</span>
                    </div>
                    <div class="rittal_box_value">
                        <span>{{ curRittalInfo.cabinetname }}</span>
                    </div>
                </div>
                <div class="rittal_box_line">
                    <div class="rittal_box_label">
                        <span>告警：</span>
                    </div>
                    <div class="rittal_box_value">
                        <span>{{ curRittalInfo.cabinetname }}</span>
                    </div>
                </div>
                <div class="rittal_box_line">
                    <div class="rittal_box_label">
                        <span>厂家：</span>
                    </div>
                    <div class="rittal_box_value">
                        <span>{{ curRittalInfo.cabinetname }}</span>
                    </div>
                </div>
            </div>
         </div>

         <!-- 单机u位的u位展示详情 -->
        <div class="rittal_box" ref="bitBoxRef">
            <div class="rittal_box_top">
                <span>u位详细信息</span>
                <div class="close_icon" @click="closeBitDialog">
                    <el-icon><Close /></el-icon>
                </div>
            </div>
            <div class="rittal_box_content">
                <div class="rittal_box_line">
                    <div class="rittal_box_label">
                        <span>资产名称：</span>
                    </div>
                    <div class="rittal_box_value">
                        <span>{{ clickForm.assetName  }}</span>
                    </div>
                </div>
                <div class="rittal_box_line">
                    <div class="rittal_box_label">
                        <span>品牌：</span>
                    </div>
                    <div class="rittal_box_value">
                        <span>{{ clickForm.assetBrand  }}</span>
                    </div>
                </div>
                <div class="rittal_box_line">
                    <div class="rittal_box_label">
                        <span>型号：</span>
                    </div>
                    <div class="rittal_box_value">
                        <span>{{ clickForm.assetModel }}</span>
                    </div>
                </div>
                <div class="rittal_box_line">
                    <div class="rittal_box_label">
                        <span>运营状态</span>
                    </div>
                    <div class="rittal_box_value">
                        <span>{{ clickForm.assetStatus }}</span>
                    </div>
                </div>
                <div class="rittal_box_line">
                    <div class="rittal_box_label">
                        <span>起始u位：</span>
                    </div>
                    <div class="rittal_box_value">
                        <span>{{ clickForm.assetBeginU }}</span>
                    </div>
                </div>
                <div class="rittal_box_line">
                    <div class="rittal_box_label">
                        <span>结束u位</span>
                    </div>
                    <div class="rittal_box_value">
                        <span>{{ clickForm.assetEndU }}</span>
                    </div>
                </div>

            </div>
        </div>

    </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted, onBeforeUnmount } from "vue"
import * as THREE from "three"
import * as TWEEN from "@tweenjs/tween.js"
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'

import { getAllRittalListAPI, getRittalInfoAPI, getBitListAPI } from '@/api/room/roomCom'


import { createRoom, createRittal, createRittalInfo } from './createModel'
import { EditModel } from './modelEdit'
import { showSignRittal, closeSignRittal, openFrontDoor, closeFrontDoor, openAfterDoor, closeAfterDoor } from './modelAnimate'

const props = defineProps({
    "id": {
        type: String,
        default: ""
    },
    roomType:{
        type: String,
        default: "1"
    },
    config:{
        type: Object,
        default: function() {
            return {}
        }
    }
})

// 整个组件
let comRef = ref<HTMLDivElement|null>(null)
// threejs容器
let containerRef = ref<HTMLDivElement|null>(null)
// 单机机柜信息展示
let rittalRef = ref<HTMLDivElement|null>(null)
// 单机u位信息展示
let bitBoxRef = ref<HTMLDivElement|null>(null)
// 双击机柜进入机柜详情时信息展示
let rittalInfoRef = ref<HTMLDivElement|null>(null)

// 左侧展示栏展示的box内容
let leftShow = ref("leftBox")

// 当前所处的状态
let level = ref<string>("机柜");
let curMesh:any = null; // 当前查看的mesh对象
let curRittalInfo:any = ref({}) //当前展示的机柜详情
let clickMesh:any = null; //点击到的mesh对象
let clickForm:any = ref({}); //点击到的mesh对象携带的信息
let rittalInfoDom:HTMLDivElement|null = null; //机柜信息弹窗展示
let leftBtnStatus = reactive({ //左侧按钮的激活状态
    "alarm": false,
    "space": false,
    "bit": false,
    "humidity": false,
    "bearing": false,
    "powerwaste": false
})
let rittalEdit:EditModel; //机柜操作助手

// 房间的基础模型列表
let baseModelList:Array<THREE.Mesh> = []
// 所有的机柜列表
let rittalList:Array<THREE.Mesh> = []
// 所有机柜的信息列表
let rittalDataList: Array<any> = []
// 报警的机柜列表
let errorRittalList:Array<any> = []



let scene:any, renderer:any, camera:any;
let ambientLight:any;
let controls:any;
let count = 100, flickerStatus=true; //表示多少次渲染闪烁一次

// 容器的宽高
let domArea = [window.innerWidth, window.innerHeight]
// 鼠标的点击交互
let raycaster:any, mouse:any ;

const cameraPosition = [0, 500, 1000]


async function alarmFn() {
    rittalRestoreFn("alarm")
    leftBtnStatus.alarm =!leftBtnStatus.alarm
    if(leftBtnStatus.alarm) {
        const res = await getBitListAPI(props.roomType);
        let arr:any[] = [];
        (res.data||[]).forEach((ele:any)=>{
            let temp:any = rittalList.find(rittal=>{
                return (rittal.userData||{}).cabinetid==ele.cabinetid
            })
            if(Number(temp.cabinetAlarmCount) > 0) {
                arr.push(temp)
            }
        })
        errorRittalList = arr
        changeBitColor(0xD91116)
    } else {
        changeRittalColor()
        errorRittalList = []
    }

    // console.log("告警监控")
}
function spaceFn() {
    console.log("空间")
    rittalRestoreFn("space")
    leftBtnStatus.space = !leftBtnStatus.space
    rittalEdit.spaceChange(scene, leftBtnStatus.space)
}

async function bitFn() {
    // console.log("u位")
    rittalRestoreFn("bit")
    leftBtnStatus.bit =!leftBtnStatus.bit
    if(leftBtnStatus.bit) {
        const res = await getBitListAPI(props.roomType)
        rittalEdit.bitChange(scene, leftBtnStatus.bit, res.data)
    } else {
        rittalEdit.bitChange(scene, leftBtnStatus.bit)
    }
    
}

function humidityFn() {
    // console.log("湿度")
    rittalRestoreFn("humidity")
    leftBtnStatus.humidity =!leftBtnStatus.humidity
    rittalEdit.humidityChange(scene, leftBtnStatus.humidity)
}

function bearingFn() {
    rittalRestoreFn("bearing")
    leftBtnStatus.bearing =!leftBtnStatus.bearing
    rittalEdit.bearingChange(scene, leftBtnStatus.bearing)
}

function powerwasteFn() {
    rittalRestoreFn("powerwaste")
    leftBtnStatus.powerwaste =!leftBtnStatus.powerwaste
    rittalEdit.powerwasteChange(scene, leftBtnStatus.powerwaste)
}

// 恢复机房样式
function rittalRestoreFn(exclude:string="") {
    if(leftBtnStatus.alarm && exclude!=="alarm") {
        changeRittalColor()
        errorRittalList = []
        leftBtnStatus.alarm = false
    }
    if(leftBtnStatus.space && exclude!=="space") {
        leftBtnStatus.space = false
        rittalEdit.spaceChange(scene, false)
    }
    if(leftBtnStatus.bit && exclude!=="bit") {
        leftBtnStatus.bit = false
        rittalEdit.bitChange(scene, leftBtnStatus.bit)
    }
    if(leftBtnStatus.humidity && exclude!=="humidity") {
        leftBtnStatus.humidity = false
        rittalEdit.humidityChange(scene, false)
    }
    if(leftBtnStatus.bearing && exclude!=="bearing") {
        leftBtnStatus.bearing = false
        rittalEdit.bearingChange(scene, false)
    }
    if(leftBtnStatus.powerwaste && exclude!=="powerwaste") {
        leftBtnStatus.powerwaste = false
        rittalEdit.spaceChange(scene, false)
    }
}

function init(width:number, height:number) {
    domArea = [width, height]
    scene = new THREE.Scene()

    camera = new THREE.PerspectiveCamera(60, width/height, 2, 20000)
    camera.position.set(cameraPosition[0], cameraPosition[1], cameraPosition[2])

    renderer = new THREE.WebGLRenderer()
    renderer.setSize(width, height)
    renderer.setClearColor(0xffffff, 0)
    renderer.setPixelRatio(window.devicePixelRatio)
    renderer.shadowMap.enableDamping = true
    renderer.antialias = true
    containerRef.value?.appendChild(renderer.domElement)
    
    ambientLight = new THREE.AmbientLight(0xffffff, 1)
    scene.add(ambientLight)
    let point_light01 = new THREE.PointLight(0xffffff)
    point_light01.position.set(100,1000,100)
    point_light01.castShadow = true
    scene.add(point_light01)
    // 设置阴影参数
    // point_light01.shadow.camera.near = 0.5; // 阴影从这么近开始显示
    // point_light01.shadow.camera.far = 100; // 阴影到这么远结束
    // point_light01.shadow.camera.left = -10; // 阴影左边界
    // point_light01.shadow.camera.right = 10; // 阴影右边界
    // point_light01.shadow.camera.top = 10; // 阴影上边界
    // point_light01.shadow.camera.bottom = -10; // 阴影下边界
    initRoom()
}

/**u位警告颜色 */
function changeBitColor(color=0xffffff) {
    if(curMesh&&curMesh instanceof THREE.Group) {
        curMesh.children.forEach(mesh=>{
            let loop = (mesh.userData||{}).status
            if(mesh instanceof THREE.Mesh && mesh.name.includes("U位") && loop) {
                if(level.value === "单个展示") {
                    mesh.material.color.set(new THREE.Color(color))
                }
            }
        })
    }
}

/**机柜的警告颜色
 * 
 * @param color 
 */
function changeRittalColor(color=0xffffff) {
    if(!leftBtnStatus.alarm) {
        return;
    }
    errorRittalList.forEach(ele=>{
        let materials = ele.material
        if(Array.isArray(materials)) {
            materials.forEach(material=>{
                material.color.set(new THREE.Color(color))
            })
        }
    })
}

function animate() {
    count--
    if(count < 0){
        count = 100
        flickerStatus = !flickerStatus
        if(flickerStatus) {
            changeBitColor(0xD91116)
            changeRittalColor(0xD91116)
        } else {
            changeBitColor()
            changeRittalColor()
        }
    }
    TWEEN.update()
    controls.update()
    renderer.render(scene, camera)
    requestAnimationFrame(animate)
}

function resize() {
    if(!containerRef.value) return
    let width = containerRef.value.clientWidth
    let height = containerRef.value.clientHeight
    camera.aspect = width/height
    camera.updateProjectionMatrix()
    renderer.setSize(width, height)
    domArea = [width, height]
}

function initRoom(visible=true) {
    let meshList = createRoom()
    meshList.forEach(mesh=>{
        mesh.visible = visible
        scene.add(mesh)
    })
    baseModelList = meshList
}

/** 初始化机箱列表
 * 
 * @param list 机箱信息列表
 */
function initRittalList(list:Array<any>, visible=true) {
    rittalList = createRittal(list, props.config)
    rittalList.forEach(mesh=>{
        mesh.visible = visible
        scene.add(mesh)
    })
    rittalEdit = new EditModel(rittalList)
}

// 初始化轨道控制器
function initMouseContors() {
    controls = new OrbitControls(camera, renderer.domElement)
    controls.enableDamping = true
    controls.maxDistance = 1200
    controls.maxPolarAngle = Math.PI / 2;

}

/**获取点击的目标 */
function getClickMesh(event: MouseEvent, type:string="click") {
    mouse.x = ( event.offsetX / domArea[0] ) * 2 - 1;
    mouse.y = - ( event.offsetY / domArea[1] ) * 2 + 1;

    // 使用鼠标的2D位置和当前相机的位置来更新射线
    raycaster.setFromCamera(mouse, camera);
 
    // 计算物体和射线的交点
    var intersects = raycaster.intersectObjects(scene.children);
    intersects = (intersects||[]).filter((ele:any)=>{ return (ele.object||{}).visible })

    if(level.value === "机柜") {
        if(clickMesh) {
            closeRittalDialog()
        }
        let oneMesh:any = intersects[0]
        if(!oneMesh) return;
        let object = oneMesh.object
        if(object && object.name.includes("机柜")) {
            if(type === "click") { //单机机柜
                clickMesh = object
                clickForm.value = object.userData||{}
                showDialog(event)
            } else {
                curRittalInfo.value = object.userData||{}
                changSignRittal(object)
            }
            
        }
    }

    if(level.value === "单个展示") {
        if(clickMesh) {
            closeBitDialog()
        }
        let oneMesh:any = intersects[0]
        if(!oneMesh) return;
        let object = oneMesh.object
        if(type === "click") {
            if(object.name.includes("U位")) {
                clickMesh = object
                clickForm.value = {...object.userData}
                showBitDialog(event)
            }
        } else {
            if(object.name === "前门" && !object.userData.openStatus) {
                openFrontDoor(curMesh, object)
            } else if (object.name === "前门") {
                closeFrontDoor(curMesh, object)
            } else if (object.name === "后门" && !object.userData.openStatus ) {
                openAfterDoor(curMesh, object)
            } else if (object.name === "后门") {
                closeAfterDoor(curMesh, object)
            }
        }

    }
}

/**切换到单个机柜展示
 * 
 * @param mesh 目标机柜
 */
async function changSignRittal(mesh:THREE.Mesh) {
    rittalRestoreFn()
    let info = mesh.userData
    const res = await getRittalInfoAPI(info.cabinetid)
    console.log("获取到的机柜详细信息", res)
    let group = createRittalInfo(res.data)
    console.log(group)
    group.position.set(mesh.position.x, mesh.position.y, mesh.position.z)
    scene.add(group)
    curMesh = group
    showSignRittal(camera, scene, [...baseModelList,...rittalList], group)
    level.value = "单个展示"
    leftShow.value = 'rittalInfo'
}

/**显示单机机柜信息
 * 
 * @param event 
 */
function showDialog(event: MouseEvent) {
    if(!clickMesh) {
        return
    }
    if(rittalRef.value) {
        let a = getPostion(event.layerX + 5, event.layerY, 300, 300)
        rittalRef.value.style.left = a[0] + "px"
        rittalRef.value.style.top = a[1]  + "px"
        // console.log(a)
        // rittalRef.value.style.left = event.layerX + "px"
        // rittalRef.value.style.top = event.layerY - 150  + "px"
        rittalRef.value.style.display = "block"
    }
    changeColor(0x82FCFE)
}

/**关闭机柜详细信息的弹窗 */
function closeRittalDialog() {
    if(rittalRef.value) {
        rittalRef.value.style.display = "none"
    }
    changeColor()
}

/**展示单个u位的详细信息
 * 
 */
function showBitDialog(event: MouseEvent) {
    if(!clickMesh) {
        return
    }
    console.log(clickMesh)
    if(bitBoxRef.value) {
        let a = getPostion(event.layerX + 5, event.layerY, 300, 300)
        bitBoxRef.value.style.left = a[0] + "px"
        bitBoxRef.value.style.top = a[1]  + "px"
        // bitBoxRef.value.style.left = event.layerX + "px"
        // bitBoxRef.value.style.top = event.layerX - 150  + "px"
        bitBoxRef.value.style.display = "block"
    }
    changeColor(0x0564AC)
}

/**关闭u位的展示详情页
 * 
 */
function closeBitDialog() {
    if(bitBoxRef.value) {
        bitBoxRef.value.style.display = "none"
    }
    changeColor()
}

/**关闭单个机柜展示 */
function backToUp() {
    initRoom(false)
    initRittalList(rittalDataList, false)
    leftShow.value = 'leftBox'
    level.value = "机柜"
    closeSignRittal(camera, scene, [...baseModelList,...rittalList], curMesh)
    curMesh.value = null
}


// 修改颜色
function changeColor(color=0xffffff) {
    if(!clickMesh) {
        return
    }
    let materialList = clickMesh.material
    if(!Array.isArray(materialList)) {
        materialList.color.set(new THREE.Color(color))
        return
    }
    materialList.forEach(material=>{
        material.color.set(new THREE.Color(color))
    })
}

/**添加鼠标事件 */
function addMounseEnv() {
    // 创建一个raycaster实例
    raycaster = new THREE.Raycaster();
    // 创建一个二维空间的向量用于存储鼠标点击的屏幕位置
    mouse = new THREE.Vector2();
    if(containerRef.value) {
        containerRef.value.addEventListener("click", clickEnv)
        containerRef.value.addEventListener("dblclick", doubleClick)
    }
}

// 移除鼠标事件
function removeMounseEnv() {
    if(containerRef.value) {
        containerRef.value.removeEventListener("click", clickEnv)
        containerRef.value.removeEventListener("dblclick", doubleClick)
    }
}

/**鼠标单击事件 */
function clickEnv(e:MouseEvent) {
    getClickMesh(e, "click")
}

/**鼠标双击事件 */
function doubleClick(e:MouseEvent) {
    getClickMesh(e, "dblClick")
}

async function getAllRittalListFn() {
    const res = await getAllRittalListAPI(props.roomType)
    console.log("res", res)
    rittalDataList = res.data||[]
    initRittalList(rittalDataList)
}


/**计算弹窗的相对位置
 * 
 * @param ex 点击的x坐标
 * @param ey 点击的y坐标
 * @param w 弹框的宽
 * @param h 弹框的高
 */
function getPostion(ex:number,ey:number, w:number, h:number) {
    console.log(ex)
    let x = ex
    let y = ey
    if(ex + w > domArea[0]) {
        x = ex - w
    }
    if(ey + h > domArea[1]) {
        y = ey - h
    }
    return [x, y]
}



onMounted(()=>{
    if(containerRef.value) {
        init(containerRef.value.clientWidth, containerRef.value.clientHeight)
        initMouseContors()
        animate()
    }
    window.addEventListener("resize", resize)
    addMounseEnv()
    getAllRittalListFn()
})

onBeforeUnmount(()=>{
    window.removeEventListener("resize", resize)
    removeMounseEnv()
})

</script>

<style scoped lang="scss">
.room_com {
    position: relative;
    width: 100%;
    height: calc(100vh - 84px);
    background-image: url("@/assets/images/3D/bg2.jpg");
    background-size: 100% 100%;
    --border-color: #D9D9D9;
    .container_box {
        width: 100%;
        height: 100%;
    }
    .left_box {
        user-select: none;
        position: absolute;
        left: 0;
        top: 50%;
        transform: translateY(-50%);
        display: flex;
        flex-direction: column;
        align-items: center;
        border: 1px solid #fff;
        background-color: rgba($color: #333, $alpha: 0.5);
        .left_cell {
            width: 100%;
            display: flex;
            flex-direction: column;
            align-items: center;
            color: #fff;
            padding: 12px;
            cursor: pointer;
            --img-size: 36px;
            font-size: 14px;
            transition: 0.3s;
            img {
                margin-bottom: 2px;
                height: var(--img-size);
                width: auto;
            }
            border-bottom: 1px solid #fff;
        }
        .selct_left_cell {
            background-color: rgba($color: #12dfd4, $alpha: 0.5)
        }
    }
}

.rittal_box {
    top: 0;
    left: 0;
    z-index: 9;
    position: absolute;
    background-color: rgba(99, 91, 91, 0.5);
    padding: 8px;
    width: 300px;
    height: 300px;
    color: #fff;
    display: none;
    .rittal_box_top {
        width: 100%;
        position: relative;
        padding: 8px;
        display: flex;
        align-items: center;
        justify-content: center;
        border-bottom: 1px solid var(--border-color);
        .close_icon {
            position: absolute;
            top: 50%;
            right: 15px;
            transform: translateY(-50%);
            cursor: pointer;
        }
    }
    .rittal_box_content {
        width: 100%;
        padding: 8px;
        padding-bottom: 12px;
        .rittal_box_line {
            display: flex;
            align-items: center;
            margin-top: 12px;
            .rittal_box_label {
                user-select: none;
            }
            .rittal_box_value {
                margin-left: 8px;
            }
        }
        .rittal_box_use {
            margin-top: 12px;
            width: 100%;
            height: 20px;
            border: 1px solid var(--border-color);
            .rittal_width {
                width: var(--width-num);
                height: 100%;
                background-color: #99EF5B;
            }
        }
    }
}

.rittal_info {
    width: 200px;
    color: #fff;
    height: 500px;
    background-color: rgba(99, 91, 91, 0.5);
    padding: 8px;
    padding-left: 20px;
    z-index: 9;
    position: absolute;
    left: 30px;
    top: 50%;
    transform: translateY(-50%);
    .rittal_info_title {
        width: 100%;
        display: flex;
        align-items: center;
        position: relative;
        justify-content: center;
        .back_icon {
            position: absolute;
            left: 0;
            transform: translateY(4px);
            cursor: pointer;
        }
    }
    .rittal_info_contetn {
        width: 100%;
        padding: 8px;
        padding-bottom: 12px;
        .rittal_box_line {
            display: flex;
            align-items: center;
            margin-top: 12px;
            .rittal_box_label {
                user-select: none;
            }
            .rittal_box_value {
                margin-left: 8px;
            }
        }
    }
}
</style>